﻿using UnityEditor;                     // 引入 Unity 编辑器 API，用于访问 Editor-only 功能
using UnityEngine;                     // Unity 核心库
using UnityEngine.Profiling;           // 用于性能分析，比如 Profiler.BeginSample
using UnityEngine.Rendering;           // Unity 渲染管线相关 API

// 声明 CameraRenderer 类为 partial，表示它可能分散在多个文件中
// 当前文件是处理 Editor 相关功能的扩展部分
partial class CameraRenderer
{
	// 声明一些方法的 "partial" 版本，这些方法在其它文件（比如主文件）中也可能有定义
	// 这允许我们将不同功能拆分到不同文件，提高代码组织性

	partial void DrawGizmos();                      // 绘制 Gizmos（辅助线等）
	partial void DrawUnsupportedShaders();          // 绘制使用不兼容 Shader 的物体（用错误材质显示）
	partial void PrepareForSceneWindow();           // Scene 视图专用初始化逻辑
	partial void PrepareBuffer();                   // 准备 CommandBuffer（比如命名等）

#if UNITY_EDITOR
    // 以下代码仅在 Unity Editor 下编译

    // 定义一组旧的 Shader Pass Tag ID，用于兼容旧版（Built-in RP / Legacy）Shader
    // 这些 Shader Pass 在 SRP 中可能没有对应实现，因此需要特殊处理
    static ShaderTagId[] legacyShaderTagIds = {
        new ShaderTagId("Always"),       // 始终渲染
        new ShaderTagId("ForwardBase"),  // 前向渲染基础通道
        new ShaderTagId("PrepassBase"),  // 预渲染基础（旧版延迟相关）
        new ShaderTagId("Vertex"),       // 顶点光照
        new ShaderTagId("VertexLMRGBM"), // 顶点光照 + Lightmap RGBM
        new ShaderTagId("VertexLM")      // 顶点光照 + Lightmap
    };

    // 一个用于渲染不兼容 Shader 的“错误材质”
    // 当某个物体的 Shader 不被当前渲染管线支持时，使用这个材质进行高亮提示
    static Material errorMaterial;

    // 当前渲染步骤的采样名字（用于 Profiler 和 Debug）
    string SampleName { get; set; }

    /// <summary>
    /// 绘制 Gizmos（比如在 Scene 视图中的选中框、辅助线等）
    /// 仅在 Editor 下有效，并且仅在需要渲染 Gizmos 时执行
    /// </summary>
    partial void DrawGizmos()
    {
        // 检查是否应该渲染 Gizmos（比如用户是否开启了 Gizmos 显示）
        if (Handles.ShouldRenderGizmos())
        {
            // 绘制 PreImageEffects 阶段的 Gizmos（比如在摄像机效果前的辅助线）
            context.DrawGizmos(camera, GizmoSubset.PreImageEffects);
            // 绘制 PostImageEffects 阶段的 Gizmos（比如后处理之后的辅助线）
            context.DrawGizmos(camera, GizmoSubset.PostImageEffects);
        }
    }

    /// <summary>
    /// 绘制使用旧版 / 不兼容 Shader 的物体，用错误材质进行提示
    /// 这通常发生在 SRP 不认识某些 Built-in Shader Pass 时
    /// </summary>
    partial void DrawUnsupportedShaders()
    {
        // 如果错误材质还没创建，则从内置 Shader 创建一个
        if (errorMaterial == null)
        {
            errorMaterial =
                new Material(Shader.Find("Hidden/InternalErrorShader"));
        }

        // 创建 DrawingSettings，使用第一个旧版 Shader Tag，并设置一个覆盖材质（错误材质）
        var drawingSettings = new DrawingSettings(
            legacyShaderTagIds[0], new SortingSettings(camera)
        ) {
            overrideMaterial = errorMaterial  // 不兼容的物体将显示为红色错误物体
        };

        // 为其它旧版 Shader Tag 也设置支持
        for (int i = 1; i < legacyShaderTagIds.Length; i++)
        {
            drawingSettings.SetShaderPassName(i, legacyShaderTagIds[i]);
        }

        // 使用默认的 FilteringSettings（通常是所有物体）
        var filteringSettings = FilteringSettings.defaultValue;

        // 执行渲染：将那些使用旧版 Shader 的物体绘制出来（用错误材质）
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filteringSettings
        );
    }

    /// <summary>
    /// 如果当前是 Scene 视图摄像机，需要额外准备世界几何体（比如地形、静态物体等）
    /// 这是 Unity Editor Scene 视图正常显示所必需的
    /// </summary>
    partial void PrepareForSceneWindow()
    {
        // 判断当前相机是否为 Scene 视图相机
        if (camera.cameraType == CameraType.SceneView)
        {
            // 通知 SRP 渲染世界几何体（供 Scene 视图显示使用）
            ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
        }
    }

    /// <summary>
    /// 为 CommandBuffer 设置一个便于识别的名字，便于在 Profiler 中查看
    /// 同时也设置了 SampleName，用于细分性能分析
    /// </summary>
    partial void PrepareBuffer()
    {
        // 开始一段性能采样，标记为 Editor Only，避免在 Build 中统计
        Profiler.BeginSample("Editor Only");
        // 将 CommandBuffer 的名字设置为当前相机的名字，便于调试
        buffer.name = SampleName = camera.name;
        // 结束性能采样
        Profiler.EndSample();
    }

#else
	// 如果不是 Editor 环境（比如在 Build 中），使用一个固定的 SampleName
	const string SampleName = bufferName;
#endif
}